
export default function createStatementData (invoice, plays) {
    const result = {}
    result.customer = invoice.customer
    result.performances = invoice.performances.map(enrichPerformance)
    result.totalAmount = totalAmount(result.performances)
    result.totalCredits = totalCredits(result.performances)
    return result


  function enrichPerformance(aPerformance){
    const calculator = createPerformanceCalculator(aPerformance, playFor(aPerformance))
    const result = Object.assign({}, aPerformance)
    result.play = calculator.play
    result.amount = calculator.amount
    result.credits = calculator.credits
    return result
  }

    function totalAmount(performances){
      return performances.reduce((total, p) => total + p.amount, 0);
    }

    function totalCredits(performances){
      return performances.reduce((total, p) => total + p.credits, 0);
    }


    function playFor(aPerformance){
      return plays[aPerformance.playID]
    }
  }

function createPerformanceCalculator(aPerformance, aPlay){
  switch(aPlay.type){
    case "tragedy": 
      return new TragedyCalculator(aPerformance, aPlay)
    case "comedy": 
      return new ComedyCalculator(aPerformance, aPlay)
    default: 
      throw new Error(`unknown type: ${aPlay.type}`)
  }
}


class PerformanceCalculator{
  constructor(aPerformance, aPlay){
      this.performance = aPerformance
      this.play = aPlay
  }

  get amount(){
    throw new Error(`not implemented`);
  }

  get credits(){
    return Math.max(this.performance.audience - 30, 0);
  }
}

class TragedyCalculator extends PerformanceCalculator {
  get amount(){
    let result = 0
    result = 40000;
    if (this.performance.audience > 30) {
        result += 1000 * (this.performance.audience - 30);
    }
    return result;
  }
}

class ComedyCalculator extends PerformanceCalculator {
  get amount(){
    let result = 0
    result = 30000;
    if (this.performance.audience > 20) {
        result += 10000 + 500 * (this.performance.audience - 20);
    }
    result += 300 * this.performance.audience;
    return result;
  }

  get credits(){
    return super.credits + Math.floor(this.performance.audience / 5);
  }
}